package io.jee.caisan.weixin.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import io.jee.alaska.data.jpa.hibernate.condition.Operation;
import io.jee.alaska.util.Result;
import io.jee.caisan.weixin.domain.MpMaterialFile;
import io.jee.caisan.weixin.domain.MpMaterialNews;
import io.jee.caisan.weixin.domain.MpMaterialNewsArticle;
import io.jee.caisan.weixin.domain.MpMaterialNum;
import io.jee.caisan.weixin.repository.MpMaterialFileRepository;
import io.jee.caisan.weixin.repository.MpMaterialNewsRepository;
import io.jee.caisan.weixin.repository.MpMaterialNumRepository;
import io.jee.caisan.weixin.service.LogService;
import io.jee.caisan.weixin.service.MpMaterialService;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews.WxMpMaterialNewsArticle;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialNewsBatchGetResult;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialNewsBatchGetResult.WxMaterialNewsBatchGetNewsItem;

@Service
@Transactional
public class MpMaterialServiceImpl implements MpMaterialService{
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Resource
	private MpMaterialNumRepository mpMaterialNumRepository;
	
	@Resource
	private MpMaterialFileRepository mpMaterialFileRepository;
	
	@Resource
	private MpMaterialNewsRepository mpMaterialNewsRepository;
	
	@Resource
	private WxMpService wxMpService;
	
	@Resource
	private LogService LogService;
	
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	
	private boolean asyncMaterialNews = false;
	private boolean asyncMaterialImage = false;
	private boolean asyncMaterialVideo = false;
	private boolean asyncMaterialVoice = false;

	@Override
	public Result<MpMaterialNum> addLongMaterialNum() {
		MpMaterialNum mpMaterialNum = findMpMaterialNumOne();
		if(mpMaterialNum == null) {
			mpMaterialNum = new MpMaterialNum();
			mpMaterialNum.setTime(new Date());
			mpMaterialNum.setListLongMaterialNum(1);
		} else {
			mpMaterialNum.setListLongMaterialNum(mpMaterialNum.getListLongMaterialNum() + 1);
		}
		mpMaterialNumRepository.save(mpMaterialNum);
		return Result.success(mpMaterialNum);
	}

	@Override
	public Result<MpMaterialNum> addMaterialCountNum() {
		MpMaterialNum mpMaterialNum = findMpMaterialNumOne();
		if(mpMaterialNum == null) {
			mpMaterialNum = new MpMaterialNum();
			mpMaterialNum.setTime(new Date());
			mpMaterialNum.setMaterialCountNum(1);
		} else {
			mpMaterialNum.setMaterialCountNum(mpMaterialNum.getMaterialCountNum() + 1);
		}
		mpMaterialNumRepository.save(mpMaterialNum);
		return Result.success(mpMaterialNum);
	}

	@Override
	public MpMaterialNum findMpMaterialNumOne() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		Date startTime = cal.getTime();
		cal.add(Calendar.DAY_OF_MONTH, 1);
		Date endTime = cal.getTime();
		return mpMaterialNumRepository.select().where("time", Operation.GET, startTime).and("time", Operation.LET, endTime).end().unique();
	}

	@Override
	public List<MpMaterialFile> listMpMaterialFile(String type) {
		return mpMaterialFileRepository.select().where("type", type).end().list();
	}
	
	@Override
	public List<MpMaterialNews> listMpMaterialNews() {
		return mpMaterialNewsRepository.findAll();
	}
	
	private Result<MpMaterialFile> addMpMaterialFile(MpMaterialFile mpMaterialFile) {
		String mediaId = mpMaterialFile.getMediaId();
		MpMaterialFile file = mpMaterialFileRepository.select().where("mediaId", mediaId).and("type", mpMaterialFile.getType()).end().unique();
		if(file != null) {
			BeanUtils.copyProperties(mpMaterialFile, file);
		} else {
			file = mpMaterialFile;
		}
		mpMaterialFileRepository.save(file);
		return Result.success(file);
	}

	private Result<MpMaterialNews> addMpMaterialNews(MpMaterialNews mpMaterialNews) {
		String mediaId = mpMaterialNews.getMediaId();
		MpMaterialNews news = mpMaterialNewsRepository.select().where("mediaId", mediaId).end().unique();
		if(news != null) {
			BeanUtils.copyProperties(mpMaterialNews, news);
		} else {
			news = mpMaterialNews;
		}
		mpMaterialNewsRepository.save(news);
		return Result.success(news);
	}
	
	private Result<MpMaterialNum> addListLongMaterialNum() {
		MpMaterialNum mpMaterialNum = findMpMaterialNumOne();
		if(mpMaterialNum == null) {
			mpMaterialNum = new MpMaterialNum();
			mpMaterialNum.setTime(new Date());
			mpMaterialNum.setListLongMaterialNum(1);
		} else {
			mpMaterialNum.setListLongMaterialNum(mpMaterialNum.getListLongMaterialNum() + 1);
		}
		mpMaterialNumRepository.save(mpMaterialNum);
		return Result.success(mpMaterialNum);
	}

	@Async
	@Override
	public void asyncMaterialNews() {
		LogService.addSystem("开始同步图文素材");
		logger.info(">>>>开始同步图文素材<<<<");
		int itemCount = 0, offset = 0, count = 20, number = 0;
		boolean start = true;
		asyncMaterialNews = true;
		try {
			while (itemCount == count || start) {
				start = false;
				WxMpMaterialNewsBatchGetResult news = wxMpService.getMaterialService().materialNewsBatchGet(offset, count);
				//增加请求接口次数
				addListLongMaterialNum();
				offset = offset + count;
				itemCount = news.getItemCount();
				for (WxMaterialNewsBatchGetNewsItem item : news.getItems()) {
					
					LogService.addSystem("获取图文素材：" + item.getMediaId());
					logger.info(">>>>获取图文素材：{}<<<<", item.getMediaId());
					number++;
					
					MpMaterialNews mpMaterialNews = new MpMaterialNews();
					mpMaterialNews.setMediaId(item.getMediaId());
					mpMaterialNews.setUpdateTime(item.getUpdateTime());
					List<MpMaterialNewsArticle> articles = new ArrayList<>();
					for (WxMpMaterialNewsArticle wxArticle : item.getContent().getArticles()) {
						MpMaterialNewsArticle article = new MpMaterialNewsArticle();
						article.setTitle(wxArticle.getTitle());
						article.setThumbMediaId(wxArticle.getThumbMediaId());
						article.setThumbUrl(wxArticle.getThumbUrl());
						article.setUrl(wxArticle.getUrl());
						article.setDigest(wxArticle.getDigest());
						articles.add(article);
					}
					mpMaterialNews.setArticles(articles);
					//保存素材到本地
					addMpMaterialNews(mpMaterialNews);
				}
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			LogService.addSystem("获取图文素材异常：" + e.getMessage());
			logger.info(">>>>获取图文素材异常：{}<<<<", e.getMessage());
		}
		asyncMaterialNews = false;
		LogService.addSystem("同步图文素材结束，成功获取数量：" + number);
		logger.info(">>>>结束同步图文素材，成功获取数量：{}<<<<", number);
	}

	@Async
	@Override
	public void asyncMaterialImage() {
		LogService.addSystem("开始同步图片素材");
		logger.info(">>>>开始同步图片素材<<<<");
		int itemCount = 0, offset = 0, count = 20, number = 0;
		boolean start = true;
		asyncMaterialImage = true;
		try {
			while (itemCount == count || start) {
				start = false;
				WxMpMaterialFileBatchGetResult file = wxMpService.getMaterialService().materialFileBatchGet(WxConsts.MaterialType.IMAGE, offset, count);
				//增加请求接口次数
				addListLongMaterialNum();
				offset = offset + count;
				itemCount = file.getItemCount();
				for (WxMaterialFileBatchGetNewsItem item : file.getItems()) {
					
					LogService.addSystem("获取图片素材：" + item.getMediaId());
					logger.info(">>>>获取图片素材：{}<<<<", item.getMediaId());
					number++;
					
					MpMaterialFile mpMaterialFile = new MpMaterialFile();
					mpMaterialFile.setMediaId(item.getMediaId());
					mpMaterialFile.setName(item.getName());
					mpMaterialFile.setType(WxConsts.MaterialType.IMAGE);
					mpMaterialFile.setUpdateTime(item.getUpdateTime());
					mpMaterialFile.setUrl(item.getUrl());
					//保存素材到本地
					addMpMaterialFile(mpMaterialFile);
				}
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			LogService.addSystem("获取图片素材异常：" + e.getMessage());
			logger.info(">>>>获取图片素材异常：{}<<<<", e.getMessage());
		}
		asyncMaterialImage = false;
		LogService.addSystem("同步图片素材结束，成功获取数量：" + number);
		logger.info(">>>>结束同步图片素材，成功获取数量：{}<<<<", number);
	}

	@Async
	@Override
	public void asyncMaterialVideo() {
		LogService.addSystem("开始同步视频素材");
		logger.info(">>>>开始同步视频素材<<<<");
		int itemCount = 0, offset = 0, count = 20, number = 0;
		boolean start = true;
		asyncMaterialVideo = true;
		try {
			while (itemCount == count || start) {
				start = false;
				WxMpMaterialFileBatchGetResult file = wxMpService.getMaterialService().materialFileBatchGet(WxConsts.MaterialType.VIDEO, offset, count);
				//增加请求接口次数
				addListLongMaterialNum();
				offset = offset + count;
				itemCount = file.getItemCount();
				for (WxMaterialFileBatchGetNewsItem item : file.getItems()) {
					
					LogService.addSystem("获取视频素材：" + item.getMediaId());
					logger.info(">>>>获取视频素材：{}<<<<", item.getMediaId());
					number++;
					
					MpMaterialFile mpMaterialFile = new MpMaterialFile();
					mpMaterialFile.setMediaId(item.getMediaId());
					mpMaterialFile.setName(item.getName());
					mpMaterialFile.setType(WxConsts.MaterialType.VIDEO);
					mpMaterialFile.setUpdateTime(item.getUpdateTime());
					mpMaterialFile.setUrl(item.getUrl());
					//保存素材到本地
					addMpMaterialFile(mpMaterialFile);
				}
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			LogService.addSystem("获取视频素材异常：" + e.getMessage());
			logger.info(">>>>获取视频素材异常：{}<<<<", e.getMessage());
		}
		asyncMaterialVideo = false;
		LogService.addSystem("同步视频素材结束，成功获取数量：" + number);
		logger.info(">>>>结束同步视频素材，成功获取数量：{}<<<<", number);
	}

	@Async
	@Override
	public void asyncMaterialVoice() {
		LogService.addSystem("开始同步语音素材");
		logger.info(">>>>开始同步语音素材<<<<");
		
		int itemCount = 0, offset = 0, count = 20, number = 0;
		boolean start = true;
		asyncMaterialVoice = true;
		try {
			while (itemCount == count || start) {
				start = false;
				WxMpMaterialFileBatchGetResult file = wxMpService.getMaterialService().materialFileBatchGet(WxConsts.MaterialType.VIDEO, offset, count);
				//增加请求接口次数
				addListLongMaterialNum();
				offset = offset + count;
				itemCount = file.getItemCount();
				for (WxMaterialFileBatchGetNewsItem item : file.getItems()) {
					
					LogService.addSystem("获取语音素材：" + item.getMediaId());
					logger.info(">>>>获取语音素材：{}<<<<", item.getMediaId());
					number++;
					
					MpMaterialFile mpMaterialFile = new MpMaterialFile();
					mpMaterialFile.setMediaId(item.getMediaId());
					mpMaterialFile.setName(item.getName());
					mpMaterialFile.setType(WxConsts.MaterialType.VIDEO);
					mpMaterialFile.setUpdateTime(item.getUpdateTime());
					mpMaterialFile.setUrl(item.getUrl());
					//保存素材到本地
					addMpMaterialFile(mpMaterialFile);
				}
			}
		} catch (WxErrorException e) {
			e.printStackTrace();
			LogService.addSystem("同步语音素材异常：" + e.getMessage());
			logger.info(">>>>同步语音素材异常：{}<<<<", e.getMessage());
		}
		asyncMaterialVoice = false;
		LogService.addSystem("同步语音素材结束，成功获取数量：" + number);
		logger.info(">>>>结束同步语音素材，成功获取数量：{}<<<<", number);
	}

	@Override
	public Result<?> asyncResult() {
		Map<String, Boolean> map = new HashMap<>();
		map.put("asyncMaterialNews", asyncMaterialNews);
		map.put("asyncMaterialImage", asyncMaterialImage);
		map.put("asyncMaterialVideo", asyncMaterialVideo);
		map.put("asyncMaterialVoice", asyncMaterialVoice);
		return Result.success(map);
	}
	
	
}
